use clap::{arg, Command};
use std::{collections::HashMap, fs, path};

mod config;
mod server;
mod task;
mod tests;

fn cli() -> Command {
    Command::new("mmerge")
        .about("madp schema 合并助手")
        .subcommand_required(true)
        .arg_required_else_help(true)
        .allow_external_subcommands(true)
        .subcommand(Command::new("init").about("在当前目录生成config.toml文件"))
        .subcommand(
            Command::new("add")
                .about("创建合并任务")
                .arg(arg!(task: <TASK> "任务id不能为空!"))
                .arg_required_else_help(true)
                .arg(arg!(--config <CONFIG>)),
        )
        .subcommand(
            Command::new("run")
                .about("执行合并任务")
                .arg(arg!(<TASK> "任务id不能为空!"))
                .arg_required_else_help(true),
        )
        .subcommand(
            Command::new("rollback")
                .about("回滚任务")
                .arg(arg!(<TASK> "任务id不能为空!"))
                .arg_required_else_help(true),
        )
        .subcommand(
            Command::new("publish")
                .about("执行定时发版任务")
                .arg(arg!(<TASK> "任务id不能为空!"))
                .arg_required_else_help(true),
        )
        .subcommand(
            Command::new("print")
                .about("打印配置信息")
                .arg(arg!(task: [TASK])),
        )
        .subcommand(Command::new("ui").about("展示图形化界面"))
}

fn main() {
    let matches = cli().get_matches();
    match matches.subcommand() {
        Some(("init", _)) => {
            // println!("在当前文件夹生成config.toml文件")
            fs::write("./config.toml", config::DEFAULT_MADP_CONFIG).unwrap();
        }
        Some(("add", sub_matches)) => {
            // let config_path = sub_matches.get_one::<String>("CONFIG");
            let config_path = sub_matches.get_one::<String>("config").map(|s| s.as_str());
            let task_arg = sub_matches.get_one::<String>("task").map(|s| s.as_str());
            let task_config = match config_path {
                Some(pth) => fs::read_to_string(pth).unwrap(),
                _ => String::from(config::DEFAULT_TASK_CONFIG),
            };
            let task_id = task_arg.expect("required");
            let madp_config = match fs::read_to_string("./config.toml") {
                Ok(madp_config_str) => madp_config_str,
                Err(_) => String::from(config::DEFAULT_MADP_CONFIG),
            };
            let task = task::Task::new(
                task_id.to_string(),
                format!("{}\n{}", madp_config, task_config),
            );

            task.init().unwrap();
            println!("任务已创建,地址{}/{}", task.config.output, task.task_id);
        }
        Some(("run", sub_matches)) => {
            let task_id = sub_matches.get_one::<String>("TASK").expect("required");

            let madp_config_str = match fs::read_to_string("./config.toml") {
                Ok(madp_config_str) => madp_config_str,
                Err(_) => String::from(config::DEFAULT_MADP_CONFIG),
            };
            let madp_config: config::MadpConfig = toml::from_str(&madp_config_str).unwrap();
            let task_config_str = match fs::read_to_string(format!(
                "{}/{}/task.config.toml",
                madp_config.output, task_id
            )) {
                Ok(config_str) => config_str,
                Err(err) => panic!("err: {}", err),
            };
            let mut task = task::Task::new(task_id.to_string(), task_config_str);
            task.run();
        }
        Some(("publish", sub_matches)) => {
            let task_id = sub_matches.get_one::<String>("TASK").expect("required");

            let madp_config_str = match fs::read_to_string("./config.toml") {
                Ok(madp_config_str) => madp_config_str,
                Err(_) => String::from(config::DEFAULT_MADP_CONFIG),
            };
            let madp_config: config::MadpConfig = toml::from_str(&madp_config_str).unwrap();
            let task_config_str = match fs::read_to_string(format!(
                "{}/{}/task.config.toml",
                madp_config.output, task_id
            )) {
                Ok(config_str) => config_str,
                Err(err) => panic!("err: {}", err),
            };
            let mut task = task::Task::new(task_id.to_string(), task_config_str);
            task.schedule();
        }
        Some(("rollback", sub_matches)) => {
            let task_id = sub_matches.get_one::<String>("TASK").expect("required");
            let madp_config_str = match fs::read_to_string("./config.toml") {
                Ok(madp_config_str) => madp_config_str,
                Err(_) => String::from(config::DEFAULT_MADP_CONFIG),
            };
            let madp_config: config::MadpConfig = toml::from_str(&madp_config_str).unwrap();

            let task_backup_str = fs::read_to_string(format!(
                "{}/{}/backup/backup.toml",
                madp_config.output, task_id
            ))
            .unwrap();
            let task_backup_config: config::BackUp = toml::from_str(&task_backup_str).unwrap();
            let mut backup_map: HashMap<String, String> = HashMap::new();
            for (i, file) in task_backup_config.files.iter().enumerate() {
                backup_map.insert(file.to_string(), task_backup_config.origins[i].to_string());
            }
            match task::rollback(&backup_map) {
                Ok(()) => println!("回退成功！"),
                Err(err) => println!("回退失败:{}，请尝试手动会退", err),
            }
        }
        Some(("print", sub_matches)) => {
            let task = sub_matches.get_one::<String>("task").map(|s| s.as_str());
            if task.is_none() {
                println!("{}", config::DEFAULT_MADP_CONFIG);
            } else {
                let task_file = task.unwrap();
                // println!("打印文件夹{}下的task.config.toml的内容", task.unwrap())
                let mut dir = path::PathBuf::from(task_file);
                if dir.is_dir() {
                    dir.push("task.config.toml");
                    // println!("打印文件夹{}下的task.config.toml的内容", task_file)
                    println!("{}", fs::read_to_string(dir).unwrap())
                } else {
                    panic!("任务目录不存在！")
                }
            }
        }
        Some(("ui", _)) => {
            server::start();
        }
        _ => unreachable!(),
    }
}
